//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import { list_source, load_node_data, save_node_data } from '@/api/user_dataview';
import { NODE_TYPE_BASE_GROUP, NodeData } from '@/pages/DataView/compoents/local_nodes/types';
import { makeAutoObservable, runInAction } from 'mobx';
import type { ReactFlowInstance, Node as FlowNode } from 'reactflow';

export class LocalDataViewStore {
    constructor() {
        makeAutoObservable(this);
    }

    private _dataViewId = "";
    private _flowInstance: ReactFlowInstance | null = null;
    private _nodeList: FlowNode<NodeData>[] = [];

    get dataViewId() {
        return this._dataViewId;
    }

    set dataViewId(val: string) {
        runInAction(() => {
            this._dataViewId = val;
        });
    }

    get flowInstance(): ReactFlowInstance | null {
        return this._flowInstance;
    }

    set flowInstance(val: ReactFlowInstance) {
        runInAction(() => {
            this._flowInstance = val;
        });
    }

    get nodeList(): FlowNode<NodeData>[] {
        return this._nodeList;
    }

    set nodeList(val: FlowNode[]) {
        runInAction(() => {
            this._nodeList = val;
        });
    }

    updateNodePosition(nodeId: string, x: number, y: number) {
        const tmpList = this._nodeList.slice();
        const index = tmpList.findIndex(item => item.id == nodeId);
        if (index == -1) {
            return;
        }
        tmpList[index].position.x = x;
        tmpList[index].position.y = y;
        this.nodeList = tmpList;
    }

    updateNodePositionEnd(nodeId: string) {
        const tmpList = this._nodeList.slice();
        const index = tmpList.findIndex(item => item.id == nodeId);
        if (index == -1) {
            return;
        }
        if (tmpList[index].data.nodeType == NODE_TYPE_BASE_GROUP) {
            return;
        }
        //找到所有group节点
        const tmpGroupList = this._nodeList.filter(item => item.data.nodeType == NODE_TYPE_BASE_GROUP);
        const cmpNode = tmpList[index];
        if (cmpNode.parentId != undefined) {
            const oldGroup = tmpList.find(item => item.id == cmpNode.parentId);
            if (oldGroup != undefined) {
                cmpNode.position.x += oldGroup.position.x;
                cmpNode.position.y += oldGroup.position.y;
            }
        }
        for (const tmpGroup of tmpGroupList) {
            if (cmpNode.position.x > tmpGroup.position.x && cmpNode.position.y > tmpGroup.position.y &&
                (cmpNode.position.x + (cmpNode.width ?? 0)) < (tmpGroup.position.x + (tmpGroup.width ?? 0)) &&
                (cmpNode.position.y + (cmpNode.height ?? 0)) < (tmpGroup.position.y + (tmpGroup.height ?? 0))
            ) {
                cmpNode.parentId = tmpGroup.id;
                cmpNode.position.x = cmpNode.position.x - tmpGroup.position.x;
                cmpNode.position.y = cmpNode.position.y - tmpGroup.position.y;
                this.nodeList = tmpList;
                return;
            }
        }

        cmpNode.parentId = undefined;
        this.nodeList = tmpList;
    }

    updateNodeSize(nodeId: string, width: number, height: number) {
        const tmpList = this._nodeList.slice();
        const index = tmpList.findIndex(item => item.id == nodeId);
        if (index == -1) {
            return;
        }
        tmpList[index].width = width;
        tmpList[index].height = height;
        tmpList[index].data.width = width;
        tmpList[index].data.height = height;
        this.nodeList = tmpList;
    }

    updateBgColor(nodeId: string, color: string) {
        const tmpList = this._nodeList.slice();
        const index = tmpList.findIndex(item => item.id == nodeId);
        if (index == -1) {
            return;
        }
        tmpList[index].data.bgColor = color;
        this.nodeList = tmpList;
    }

    removeNode(nodeId: string) {
        const tmpList = this._nodeList.slice();
        const index = tmpList.findIndex(item => item.id == nodeId);
        if (index == -1) {
            return;
        }
        const curNode = tmpList[index];
        for (const node of tmpList) {
            if (node.parentId == nodeId) {
                node.parentId = undefined;
                node.position.x += curNode.position.x;
                node.position.y += curNode.position.y;
            }
        }
        this.nodeList = tmpList.filter(item => item.id != nodeId);
    }

    //加载，保存，重置
    async loadNodeList() {
        const dataSourceList = await list_source();
        const dataSourceIdSet = new Set<string>();
        for (const dataSource of dataSourceList) {
            dataSourceIdSet.add(dataSource.id);
        }
        const jsonStr = await load_node_data(this._dataViewId);
        const tmpNodeList = JSON.parse(jsonStr) as FlowNode<NodeData>[];
        this.nodeList = tmpNodeList.filter(node => ((node.data.dataSourceId ?? "") == "" || dataSourceIdSet.has(node.data.dataSourceId ?? "")));
    }

    async saveNodeList() {
        const jsonStr = JSON.stringify(this.nodeList);
        await save_node_data(jsonStr, this._dataViewId);
    }

}